package com.self.console.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import com.self.console.utils.SerializerUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

import java.util.*;

/**
 * 
* <p>Title: RedisService</p>
* <p>Description: </p>
* <p>Company: </p>
* @author Administrator
* @date 下午8:57:45
 */
@Component
public class RedisService {

	private final transient Logger logger = LoggerFactory.getLogger(RedisService.class);

	private static final Integer DEFAULT_EXPIRED = 60 * 60 * 4; // 默认过期时间

	@Autowired
	private RedisDelegate redisDelegate;

	public <T extends Object> void del(String... keys) {
		redisDelegate.del(keys);
	}

	public <T extends Object> List<T> mget(String... keys) {
		List<T> list = new ArrayList<T>();
		List<String> strRs = redisDelegate.mget(keys);
		for (String value : strRs) {
			Object v = SerializerUtils.deserialization(value);
			list.add((T) v);
		}
		return list;
	}

	public <T extends Object> T get(String key) {
		if (StringUtils.isBlank(key)) {
			return null;
		}
		String value = redisDelegate.get(key);
		Object v = SerializerUtils.deserialization(value);
		return (T) v;

	}

	public <T extends Object> boolean set(String key, T value) {
		return set(key, value, DEFAULT_EXPIRED);
	}

	public <T extends Object> boolean mset(Map<String, T> kvMap) {
		return mset(kvMap, DEFAULT_EXPIRED);
	}

	/**
	 * 管道方式实现mset功能支持过期时间设置
	 */
	public <T extends Object> boolean mset(Map<String, T> kvMap, int expiredSeconds) {
		if (kvMap == null) {
			return false;
		}
		Jedis client = null;
		try {
			client = redisDelegate.getClient();
			Pipeline pipeline = client.pipelined();

			for (Map.Entry<String, T> e : kvMap.entrySet()) {
				T value = e.getValue();
				String key = e.getKey();
				if (value instanceof String) {
					pipeline.setex(key, expiredSeconds, (String) value);
				} else {
					String jsonString = JSON.toJSONString(value, SerializerFeature.WriteClassName);
					pipeline.setex(key, expiredSeconds, jsonString);
				}
			}

			pipeline.sync();
			pipeline.setClient(null);
			pipeline = null;
		} catch (Exception e) {
			if (null != client) {
				client.disconnect();
			}
			logger.error(e.getMessage(), e);
		} finally {
			if (null != client) {
				redisDelegate.returnResource(client);
			}
		}

		return true;
	}

	/**
	 * 返回Set类型的集合
	 */
	public <T extends Object> Set<T> getSet(String key) {

		Jedis client = null;
		try {

			client = redisDelegate.getClient();

			List<String> strValues = client.lrange(key, 0, -1);
			if (strValues == null) {
				return null;
			}
			Set<T> values = Sets.newHashSet();
			for (String strValue : strValues) {
				Object v = SerializerUtils.deserialization(strValue);
				values.add((T) v);
			}
			return values;
		} catch (Exception e) {
			if (null != client) {
				client.disconnect();
			}
			logger.error(e.getMessage(), e);
		} finally {
			if (null != client) {
				redisDelegate.returnResource(client);
			}
		}

		return new HashSet<T>(0);
	}

	public <T extends Object> Long set(String key, Set<T> values) {
		if (null == values || null == key) {
			return -1l;
		}
		List<String> strValues = Lists.newArrayList();
		for (T value : values) {
			if (value instanceof String) {
				strValues.add((String) value);
			} else {
				String jsonString = JSON.toJSONString(value, SerializerFeature.WriteClassName);
				strValues.add(jsonString);
			}
		}

		Jedis client = null;
		try {

			client = redisDelegate.getClient();
			client.del(key);
			return client.lpush(key, strValues.toArray(new String[values.size()]));
		} catch (Exception e) {
			if (null != client) {
				client.disconnect();
			}
			logger.error(e.getMessage(), e);
		} finally {
			if (null != client) {
				redisDelegate.returnResource(client);
			}
		}

		return null;
	}

	public <T extends Object> boolean set(String key, T value, int expiredSeconds) {
		if (value == null) {
			return false;
		}
		if (value instanceof String) {
			redisDelegate.setex(key, expiredSeconds, (String) value);
		} else {
			String jsonString = JSON.toJSONString(value, SerializerFeature.WriteClassName);
			redisDelegate.setex(key, expiredSeconds, jsonString);
		}
		return true;

	}

	public Long ttl(String key) {
		return redisDelegate.ttl(key);
	}

	public void flushRedis() {
		redisDelegate.flushRedis();
	}
	
	public Long expire(String key, int expiredSeconds) {
		return redisDelegate.expire(key, expiredSeconds);
	}
	
	public Long setnx(String key, String value) {
		return redisDelegate.setnx(key, value);
	}
	
	public Long incr(String key) {
		return redisDelegate.incr(key);
	}
}
